﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using CommonTypes.Server;

namespace Server.Model
{
    public class ServersInformation
    {
        private readonly SortedDictionary<String, IServerToServer> _serversProxy;
        private readonly SortedDictionary<String, String> _serversLocation;
        private readonly SortedDictionary<String, bool> _activeServers;

        private bool _isPrimary;
        private String _primaryId;

        private readonly Object _dictionaryLock = new object( );

        private readonly ReaderWriterLockSlim _primaryIdLock = new ReaderWriterLockSlim( );

        public ServersInformation( )
        {
            _serversProxy = new SortedDictionary<string, IServerToServer>( );
            _serversLocation = new SortedDictionary<string, String>( );
            _activeServers = new SortedDictionary<string, bool>( );
            _isPrimary = true;
            _primaryId = null;
        }

        public void parseServerLocation( String serverParserFile )
        {
            if( !File.Exists( serverParserFile ) )
                throw new FileNotFoundException( );

            using( TextReader reader = new StreamReader( serverParserFile ) )
            {
                for( int index = 0; index < 4; index++ )
                {
                    String serverId = reader.ReadLine( );
                    String serverLocation = reader.ReadLine( );
                    _serversLocation.Add( serverId, serverLocation );
                    _activeServers.Add( serverId, true );
                }
            }
        }

        public void getServersProxies( String currentServerId )
        {
            foreach( String serverId in ServersLocation.Keys )
            {
                if( serverId != currentServerId )
                {
                    String serverAddress = ServersLocation[ serverId ];

                    IServerToServer server = ( IServerToServer )Activator.GetObject( typeof( IServerToServer ), serverAddress + "/ServerToServer" );
                    ServersProxy.Add( serverId, server );
                }
            }
        }

        public SortedDictionary<String, IServerToServer> ServersProxy
        {
            get
            {
                SortedDictionary<String, IServerToServer> tmp;
                lock( _dictionaryLock )
                    tmp = _serversProxy;
                return tmp;
            }
        }

        public SortedDictionary<String, bool> ActiveServers
        {
            get
            {
                SortedDictionary<String, bool> tmp;
                lock( _dictionaryLock )
                    tmp = _activeServers;
                return tmp;
            }
        }

        public SortedDictionary<String, String> ServersLocation
        {
            get
            {
                SortedDictionary<String, String> tmp;
                lock( _dictionaryLock )
                    tmp = _serversLocation;
                return tmp;
            }
        }

        public String PrimaryLocation
        {
            get
            {
                String ret;
                _primaryIdLock.EnterReadLock( );
                ret = _serversLocation[ _primaryId ];
                _primaryIdLock.ExitReadLock( );
                return ret;
            }

            set
            {
                _primaryIdLock.EnterWriteLock( );
                _serversLocation[ _primaryId ] = value;
                _primaryIdLock.ExitWriteLock( );
            }
        }

        public String PrimaryId
        {
            get
            {
                String ret;
                _primaryIdLock.EnterReadLock( );
                ret = _primaryId;
                _primaryIdLock.ExitReadLock( );
                return ret;
            }

            set
            {
                _primaryIdLock.EnterWriteLock( );
                _primaryId = value;
                _primaryIdLock.ExitWriteLock( );
            }
        }

        public bool Primary
        {
            get
            {
                bool ret;
                _primaryIdLock.EnterReadLock( );
                ret = _isPrimary;
                _primaryIdLock.ExitReadLock( );
                return ret;
            }

            set
            {
                _primaryIdLock.EnterWriteLock( );
                _isPrimary = value;
                _primaryIdLock.ExitWriteLock( );
            }
        }
    }
}